package com.mjk.common.core.jdbc.ctable;


import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.core.jdbc.annotation.ArcSharding;
import com.mjk.common.core.jdbc.service.plus.wrap.BeeQueryWrapper;
import com.mjk.common.core.jdbc.sphere.impl.table.CapacityPreciseShardingAlgorithm;
import com.mjk.common.tools.springextend.BeeSpringBean;
import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;

import java.util.*;


@Intercepts({ @Signature(method = "update", type = Executor.class, args = { MappedStatement.class, Object.class }) })
public class ShardingInterceptor implements Interceptor{
	private final String PARAM = "param1";
	private final Object ower = new Object();
	private final Map<String,Object> shardingTableMap = new HashMap<>();
	public ShardingInterceptor() {
		List<String> noDataSource = new ArrayList<>();
		noDataSource.add("no");
	}
	@Override
    public Object intercept(Invocation invocation) throws Throwable {		
        MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
        Object paramObj = invocation.getArgs()[1];
        return switch (ms.getSqlCommandType()) {
            case INSERT -> {
                processInsert(ms, paramObj);
                yield invocation.proceed();
            }
            case DELETE -> {
                processDelete(ms, paramObj);
                yield invocation.proceed();
            }
            default -> invocation.proceed();
        };
    }

	private synchronized void processDelete(MappedStatement ms, Object paramObj) {
		if (paramObj == null) {
            return;
        }
		
		ArcSharding sharding = paramObj.getClass().getAnnotation(ArcSharding.class);
		if(sharding == null) {
			return ;
		}
		
		BoundSql boundSql = ms.getBoundSql(paramObj);
		//如果是删除母表的操作，顺便把分表删除
		//如果删除不带条件 则删除 分表
		if(!boundSql.getSql().endsWith(sharding.table())){
			return;
		}
		//LexerEngine lexerEngine = LexerEngineFactory.newInstance(DatabaseType.MySQL, boundSql.getSql());
        //lexerEngine.nextToken();
        //SQLStatement result = SQLParserFactory.newInstance(DatabaseType.MySQL, null, null, "").parse();
        //if ( ObjectUtils.equals(sharding.table(), result.getTables().getSingleTableName())) {  
            //shardingInfo里面包行了分了多少张表
            ShardingInfo shardingInfo = CapacityPreciseShardingAlgorithm.sharding(sharding);
            if (!shardingInfo.isUseCommonTable()) {
                //这里定义一个mapper 处理啊删除表工作（drop table）
            	for(String tabName : shardingInfo.getShardingList()) {
            		ShardingTableService shardingTableService = (ShardingTableService) BeeSpringBean.getBean("shardingTableService");
            		shardingTableService.delTable(tabName);   
            	}
            //}
            shardingTableMap.remove(sharding.table());
        }
	}
	private void processInsert(MappedStatement ms, Object paramObj) {
		if (paramObj == null) {
            return;
        }
		ParamMap tmp = (ParamMap)paramObj;
		ArcSharding sharding = null;
		//适配批量插入
		if(tmp.get(PARAM) instanceof List list){
			sharding = list.get(0).getClass().getAnnotation(ArcSharding.class);
		}else{
			sharding = tmp.get(PARAM).getClass().getAnnotation(ArcSharding.class);
		}

		if(sharding == null) {
            BeeQueryWrapper wrapper = (BeeQueryWrapper) tmp.get("param1");
            sharding = wrapper.getInstance().getClass().getAnnotation(ArcSharding.class);
            if (sharding == null) {
                return;
            }
		}

		if (shardingTableMap.containsKey(sharding.table())) {
			return;
		} else {
			shardingTableMap.put(sharding.table(), sharding.table());
		}

//		BoundSql boundSql = ms.getBoundSql(paramObj);
//		LexerEngine lexerEngine = LexerEngineFactory.newInstance(DatabaseType.MySQL, boundSql.getSql());
//        lexerEngine.nextToken();
//        SQLStatement result = SQLParserFactory.newInstance(DatabaseType.MySQL, lexerEngine.getCurrentToken().getType(),
//                 new ShardingRule(new ShardingRuleConfiguration(), noDataSource), lexerEngine, null).parse();
//        if ((result instanceof DMLStatement) && ObjectUtils.equals(sharding.table(), result.getTables().getSingleTableName())) {        	
            ShardingInfo shardingInfo = CapacityPreciseShardingAlgorithm.sharding(sharding);
            if (!shardingInfo.isUseCommonTable()) {
                //传入表名称和 创建表的语句

            	ShardingTableService shardingTableService = (ShardingTableService) BeeSpringBean.getBean("shardingTableService");
//				for (String tabName : shardingInfo.getShardingList()) {
				shardingTableService.createTable((BaseEntity)tmp.get("param1"));
//					try {
//						jdbcTemplate.execute(SqlProviderUtils.buildCreateTabSql(tabName, paramObj));
//					}catch (Exception e){
//						e.printStackTrace();
//					}
//				}

            }
//        }
	}
	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
		// Do nothing
	}
	
}
